package com.rub.android.extension

import android.content.Context
import android.content.SharedPreferences
import java.io.IOException
import java.lang.IllegalArgumentException
import java.lang.reflect.Method
import kotlin.jvm.Throws

/**
 * 简化SharedPreferences调用。
 *
 * @param action 拥有SharedPreferences.Editor对象上下文的回调代码块
 */
fun SharedPreferences.edit(action: SharedPreferences.Editor.() -> Unit) {
    val editor = edit()
    action(editor)
    editor.apply()
}


/**
 * 保存在手机里面的文件名
 */
const val FILE_NAME = "share_data"

/**
 * 保存数据的方法，我们需要拿到保存数据的具体类型，然后根据类型调用不同的保存方法
 *
 * @param context
 * @param key
 * @param object
 */
fun put(context: Context, key: String?, `object`: Any) {
    val sp: SharedPreferences = context.getSharedPreferences(
        FILE_NAME,
        Context.MODE_PRIVATE
    )
    val editor = sp.edit()
    when (`object`) {
        is String -> {
            editor.putString(key, `object`)
        }
        is Int -> {
            editor.putInt(key, `object`)
        }
        is Boolean -> {
            editor.putBoolean(key, `object`)
        }
        is Float -> {
            editor.putFloat(key, `object`)
        }
        is Long -> {
            editor.putLong(key, `object`)
        }
        else -> {
            editor.putString(key, `object`.toString())
        }
    }
    SharedPreferencesCompat.apply(editor)
}

/**
 * 得到保存数据的方法，我们根据默认值得到保存的数据的具体类型，然后调用相对于的方法获取值
 *
 * @param context
 * @param key
 * @param defaultObject
 * @return
 */
fun get(context: Context, key: String?, defaultObject: Any?): Any? {
    val sp: SharedPreferences = context.getSharedPreferences(
        FILE_NAME,
        Context.MODE_PRIVATE
    )
    when (defaultObject) {
        is String -> {
            return sp.getString(key, defaultObject as String?)
        }
        is Int -> {
            return sp.getInt(key, (defaultObject as Int?)!!)
        }
        is Boolean -> {
            return sp.getBoolean(key, (defaultObject as Boolean?)!!)
        }
        is Float -> {
            return sp.getFloat(key, (defaultObject as Float?)!!)
        }
        is Long -> {
            return sp.getLong(key, (defaultObject as Long?)!!)
        }
        else -> return null
    }
}

/**
 * 移除某个key值已经对应的值
 * @param context
 * @param key
 */
fun remove(context: Context, key: String?) {
    val sp: SharedPreferences = context.getSharedPreferences(
        FILE_NAME,
        Context.MODE_PRIVATE
    )
    val editor = sp.edit()
    editor.remove(key)
    SharedPreferencesCompat.apply(editor)
}

/**
 * 清除所有数据
 * @param context
 */
fun clear(context: Context) {
    val sp: SharedPreferences = context.getSharedPreferences(
        FILE_NAME,
        Context.MODE_PRIVATE
    )
    val editor = sp.edit()
    editor.clear()
    SharedPreferencesCompat.apply(editor)
}

/**
 * 查询某个key是否已经存在
 * @param context
 * @param key
 * @return
 */
fun contains(context: Context, key: String?): Boolean {
    val sp: SharedPreferences = context.getSharedPreferences(
        FILE_NAME,
        Context.MODE_PRIVATE
    )
    return sp.contains(key)
}

/**
 * 返回所有的键值对
 *
 * @param context
 * @return
 */
fun getAll(context: Context): Map<String?, *>? {
    val sp: SharedPreferences = context.getSharedPreferences(
        FILE_NAME,
        Context.MODE_PRIVATE
    )
    return sp.all
}

/**
 * 创建一个解决SharedPreferencesCompat.apply方法的一个兼容类
 *
 * @author zhy
 */
private object SharedPreferencesCompat {

    private val sApplyMethod: Method? = findApplyMethod()

    /**
     * 反射查找apply的方法
     *
     * @return
     */
    private fun findApplyMethod(): Method? {
        try {
            val clz: Class<*> = SharedPreferences.Editor::class.java
            return clz.getMethod("apply")
        } catch (e: NoSuchMethodException) {
        }
        return null
    }

    /**
     * 如果找到则使用apply执行，否则使用commit
     *
     * @param editor
     */
    @Throws(Exception::class)
    fun apply(editor: SharedPreferences.Editor) {
        if (sApplyMethod != null) {
            sApplyMethod.invoke(editor)
            return
        }
        editor.commit()
    }
}